/******************************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Ltd.                       */
/*                                                                            */
/*  NAME      = db2_reply_msg.c                                               */
/*  NOTE      = TDS 请求解析                                                  */
/*  DATE      = 2015/03/19 by zhengxd                                         */
/******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

#include "db2_param.h"
#include "db2_froca.h"
#include "db2_reply_msg.h"


/*******************************************************************************
*  FUNC     :  解析SQLCARD
*  ARGS     :  p_st_private (DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*           :  p_i_sqlcode(SQLCODE)
*           :  p_sqlstate(SQLSTATE)
*           :  p_i_effect_rows(effect rows)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :  p_sqlstate必须是长度大于等于6
*******************************************************************************/
int db2_parse_sqlcard(L7session_db2_private *p_st_private
                     , int i_whole_flg
                     , int *p_i_sqlcode
                     , char *p_sqlstate
                     , unsigned long *p_ul_effect_rows)
{
    /* SQLCARD格式:
    *  SQLCARD = SQLCAGRP
    */
    int i_ret = APM_L7_ANALYZE_SUCC;

    i_ret = db2_parse_sqlcagrp(p_st_private, i_whole_flg, p_i_sqlcode
                              , p_sqlstate, p_ul_effect_rows);
    if (i_ret != APM_L7_ANALYZE_SUCC)
    {
        return i_ret;
    }

    /* 解析完了之后的DDM剩余长度应该是0 */
    if (p_st_private->p_st_fragment->ui_left_ddm_len)
    {
        return APM_L7_ANALYZE_FAIL;
    }

    p_st_private->p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析ACCRDBRM
*  ARGS     :  p_st_private (DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_parse_accrdbrm(L7session_db2_private *p_st_private, int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_param_cp = 0;
    unsigned int ui_param_bd_len = 0;
    char *p_typdefnam = NULL;
    L7_resp_db2 *p_st_resp = p_st_private->p_st_resp;
    L7session_db2 *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析参数 */
    while (p_st_fragment->ui_left_ddm_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("ACCRDBRM: need more data or get parameter info failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            case DRDA_CP_SVRCOD:
                /* 根据协议SVRCOD parameter的长度是6, 即body长度是2 */
                if (ui_param_bd_len != 2)
                {
                    frdbg("SECCHKRM: parameter length is incorrect!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                i_ret = db2_get_bindr(p_st_data, 2, i_whole_flg
                                     , &p_st_resp->i64_svrcod
                                     , &p_st_fragment->ui_left_ddm_len);
                break;

            /* 所有parameter都不取值,直接跳过 */
            case DRDA_CP_CRRTKN:
            case DRDA_CP_IPADDR:
            case DRDA_CP_PKGDFTCST:
            case DRDA_CP_PRDID:
            case DRDA_CP_RDBINTTKN:
            case DRDA_CP_SNAADDR:
            case DRDA_CP_SRVLST:
            case DRDA_CP_TRUST:
            case DRDA_CP_TYPDEFOVR:
            case DRDA_CP_USRID:
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                       , &p_st_fragment->ui_left_ddm_len);
                break;

            /* 取得服务端TYPDEFNAM */
            case DRDA_CP_TYPDEFNAM:
                i_ret = db2_get_chrstrdr(p_st_data, ui_param_bd_len
                                        , i_whole_flg, p_st_sess->arr_ccsid
                                        , &p_typdefnam
                                        , &p_st_fragment->ui_left_ddm_len);
                /* 判断解析结果 */
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("ACCRDBRM: need more data or parse failed!\n");
                    return i_ret;
                }

                i_ret = db2_typdef_str2int(p_typdefnam, &p_st_sess->i_ser_typdef);
                db2_free((void **)&p_typdefnam);
                if (i_ret != APM_L7_ANALYZE_SUCC)
                {
                    frdbg("ACCRDBRM: TYPDEFNAM is undefined!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                break;

            case DRDA_CP_SRVDGN:
                /* 取得服务器诊断信息*/
                /* RDBNFNRM中有两个SRVDGN参数, 实际情况不会发生 */
                if (p_st_resp->p_error_msg)
                {
                    frfree(p_st_resp->p_error_msg);
                    p_st_resp->p_error_msg = NULL;
                }
                /* 注意: SRVDGN字段协议定义成BYTSTRDR, 实际上DB2将其当做NAMDR */
                i_ret = db2_get_chrstrdr(p_st_data, ui_param_bd_len, i_whole_flg
                                        , p_st_sess->arr_ccsid
                                        , &p_st_resp->p_error_msg
                                        , &p_st_fragment->ui_left_ddm_len);
                break;

            default:
                frdbg("ACCRDBRM: Unknow parameter!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 数据不足或者解析出错 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("ACCRDBRM: need more data or parse failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* 根据协议可知svrcod是4时, sqlstate是01539 */
    if (p_st_resp->i64_svrcod == 4 && p_st_resp->i_error_code == 0)
    {
        snprintf(p_st_resp->arr_sqlstate, sizeof(p_st_resp->arr_sqlstate), "01539");
        /* sqlstate是01539时error code为+863 */
        p_st_resp->i_error_code = 863;
    }
    p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析SECCHKRM
*  ARGS     :  p_st_private (DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_parse_secchkrm(L7session_db2_private *p_st_private, int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_param_cp = 0;
    int64_t i64_svcerrno = -922;
    unsigned int ui_param_bd_len = 0;
    L7_resp_db2 *p_st_resp = p_st_private->p_st_resp;
    L7session_db2 *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析参数 */
    while (p_st_fragment->ui_left_ddm_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("SECCHKRM: need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            case DRDA_CP_SVRCOD:
                /* 根据协议SVRCOD parameter的长度是6, 即body长度是2 */
                if (ui_param_bd_len != 2)
                {
                    frdbg("SECCHKRM: parameter length is incorrect!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                i_ret = db2_get_bindr(p_st_data, 2, i_whole_flg
                                     , &p_st_resp->i64_svrcod
                                     , &p_st_fragment->ui_left_ddm_len);
                break;

            case DRDA_CP_SVCERRNO:
                /* 取得error code todo */
                i_ret = db2_get_bindr(p_st_data, 2, i_whole_flg, &i64_svcerrno
                                     , &p_st_fragment->ui_left_ddm_len);
                break;

            case DRDA_CP_SECCHKCD:
            case DRDA_CP_SECTKN:
            case DRDA_CP_USRREGNM:
                /* SECCHKCD/SECTKN/USRREGNM不取值 */
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            case DRDA_CP_SRVDGN:
                /* 取得服务器诊断信息*/
                /* RDBNFNRM中有两个SRVDGN参数, 实际情况不会发生 */
                if (p_st_resp->p_error_msg)
                {
                    frfree(p_st_resp->p_error_msg);
                    p_st_resp->p_error_msg = NULL;
                }
                /* 注意: SRVDGN字段协议定义成BYTSTRDR, 实际上DB2将其当做NAMDR */
                i_ret = db2_get_chrstrdr(p_st_data, ui_param_bd_len, i_whole_flg
                                        , p_st_sess->arr_ccsid
                                        , &p_st_resp->p_error_msg
                                        , &p_st_fragment->ui_left_ddm_len);
                break;

            default:
                frdbg("SECCHKRM: Unknow parameter!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断取值正误 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("SECCHKRM: need more data or parse failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* 根据协议可知svrcod是8时, sqlstate是42505 */
    if (p_st_resp->i64_svrcod == 8 && p_st_resp->i_error_code == 0)
    {
        snprintf(p_st_resp->arr_sqlstate, sizeof(p_st_resp->arr_sqlstate), "42505");
        /* 设置error code */
        p_st_resp->i_error_code = (int)i64_svcerrno;
    }
    p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析ENDUOWRM
*  ARGS     :  p_st_private (DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_parse_enduowrm(L7session_db2_private *p_st_private, int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_param_cp = 0;
    unsigned int ui_param_bd_len = 0;
    L7_resp_db2 *p_st_resp = p_st_private->p_st_resp;
    L7session_db2 *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析参数 */
    while (p_st_fragment->ui_left_ddm_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("ENDDTARM: need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            case DRDA_CP_SVRCOD:
                /* 根据协议SVRCOD parameter的长度是6, 即body长度是2 */
                if (ui_param_bd_len != 2)
                {
                    frdbg("ENDDTARM: parameter length is incorrect!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                i_ret = db2_get_bindr(p_st_data, 2, i_whole_flg
                                     , &p_st_resp->i64_svrcod
                                     , &p_st_fragment->ui_left_ddm_len);
                break;

            case DRDA_CP_UOWDSP:  //unit of work disposition
            case DRDA_CP_RLSCONV: //release connection
            case DRDA_CP_RDBNAM:  //Relational Database Name
                /* RDBNAM/UOWDSP/RLSCONV不取值 */
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            case DRDA_CP_SRVDGN:
                /* 取得服务器诊断信息*/
                /* RDBNFNRM中有两个SRVDGN参数, 实际情况不会发生 */
                if (p_st_resp->p_error_msg)
                {
                    frfree(p_st_resp->p_error_msg);
                    p_st_resp->p_error_msg = NULL;
                }
                /* 注意: SRVDGN字段协议定义成BYTSTRDR, 实际上DB2将其当做NAMDR */
                i_ret = db2_get_chrstrdr(p_st_data, ui_param_bd_len, i_whole_flg
                                        , p_st_sess->arr_ccsid
                                        , &p_st_resp->p_error_msg
                                        , &p_st_fragment->ui_left_ddm_len);
                break;

            default:
                frdbg("ENDDTARM: Unknow parameter!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断取值正误 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("ENDDTARM: need more data or parse failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* 根据协议可知svrcod是4时,sqlstate在SQLCARD中取得warning */
    p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析CMDVLTRM
*  ARGS     :  p_st_private (DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_parse_cmdvltrm(L7session_db2_private *p_st_private, int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_param_cp = 0;
    unsigned int ui_param_bd_len = 0;
    L7_resp_db2 *p_st_resp = p_st_private->p_st_resp;
    L7session_db2 *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析参数 */
    while (p_st_fragment->ui_left_ddm_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("CMDVLTRM: need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            case DRDA_CP_SVRCOD:
                /* 根据协议SVRCOD parameter的长度是6, 即body长度是2 */
                if (ui_param_bd_len != 2)
                {
                    frdbg("CMDVLTRM: parameter length is incorrect!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                i_ret = db2_get_bindr(p_st_data, 2, i_whole_flg
                                     , &p_st_resp->i64_svrcod
                                     , &p_st_fragment->ui_left_ddm_len);
                break;

            case DRDA_CP_RDBNAM:  //Relational Database Name
                /* RDBNAM不取值 */
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            case DRDA_CP_SRVDGN:
                /* 取得服务器诊断信息*/
                /* RDBNFNRM中有两个SRVDGN参数, 实际情况不会发生 */
                if (p_st_resp->p_error_msg)
                {
                    frfree(p_st_resp->p_error_msg);
                    p_st_resp->p_error_msg = NULL;
                }
                /* 注意: SRVDGN字段协议定义成BYTSTRDR, 实际上DB2将其当做NAMDR */
                i_ret = db2_get_chrstrdr(p_st_data, ui_param_bd_len, i_whole_flg
                                        , p_st_sess->arr_ccsid
                                        , &p_st_resp->p_error_msg
                                        , &p_st_fragment->ui_left_ddm_len);
                break;

            default:
                frdbg("CMDVLTRM: Unknow parameter!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断取值正误 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("CMDVLTRM: need more data or parse failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* 根据协议可知svrcod是8时,sqlstate为58008 */
    if (p_st_resp->i64_svrcod == 8 && p_st_resp->i_error_code == 0)
    {
        snprintf(p_st_resp->arr_sqlstate, sizeof(p_st_resp->arr_sqlstate), "58008");
        /* 58008对应的error code是: -30000 */
        p_st_resp->i_error_code = -30000;
    }
    p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
    return APM_L7_ANALYZE_SUCC;
}

/*******************************************************************************
*  FUNC     :  解析CMMRQSRM
*  ARGS     :  p_st_private (DB2私有数据)
*           :  i_whole_flg(packet是否完整)
*  RTN      :  APM_L7_ANALYZE_SUCC  (success)
*              APM_L7_ANALYZE_TODO  (more data)
*              APM_L7_ANALYZE_FAIL  (failed)
*  NOTE     :
*******************************************************************************/
int db2_parse_cmmrqsrm(L7session_db2_private *p_st_private, int i_whole_flg)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    int i_param_cp = 0;
    unsigned int ui_param_bd_len = 0;
    L7_resp_db2 *p_st_resp = p_st_private->p_st_resp;
    L7session_db2 *p_st_sess = p_st_private->p_st_sess;
    L7_fragment_db2 *p_st_fragment = p_st_private->p_st_fragment;
    Frbyte_Packet *p_st_data = p_st_fragment->p_st_data;

    /* 解析参数 */
    while (p_st_fragment->ui_left_ddm_len)
    {
        i_ret = db2_get_param_hd_info(p_st_fragment, i_whole_flg
                                     , &p_st_fragment->ui_left_ddm_len
                                     , &i_param_cp, &ui_param_bd_len);
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("CMMRQSRM: need more data or parse failed!\n");
            return i_ret;
        }

        switch (i_param_cp)
        {
            case DRDA_CP_SVRCOD:
                /* 根据协议SVRCOD parameter的长度是6, 即body长度是2 */
                if (ui_param_bd_len != 2)
                {
                    frdbg("CMMRQSRM: parameter length is incorrect!\n");
                    return APM_L7_ANALYZE_FAIL;
                }
                i_ret = db2_get_bindr(p_st_data, 2, i_whole_flg
                                     , &p_st_resp->i64_svrcod
                                     , &p_st_fragment->ui_left_ddm_len);
                break;

            case DRDA_CP_CMMTYP:  //Commitment Request Type
            case DRDA_CP_RDBNAM:  //Relational Database Name
                /* RDBNAM/UOWDSP/RLSCONV不取值 */
                i_ret = db2_skip_param(p_st_data, ui_param_bd_len, i_whole_flg
                                      , &p_st_fragment->ui_left_ddm_len);
                break;

            case DRDA_CP_SRVDGN:
                /* 取得服务器诊断信息*/
                /* RDBNFNRM中有两个SRVDGN参数, 实际情况不会发生 */
                if (p_st_resp->p_error_msg)
                {
                    frfree(p_st_resp->p_error_msg);
                    p_st_resp->p_error_msg = NULL;
                }
                /* 注意: SRVDGN字段协议定义成BYTSTRDR, 实际上DB2将其当做NAMDR */
                i_ret = db2_get_chrstrdr(p_st_data, ui_param_bd_len, i_whole_flg
                                        , p_st_sess->arr_ccsid
                                        , &p_st_resp->p_error_msg
                                        , &p_st_fragment->ui_left_ddm_len);
                break;

            default:
                frdbg("CMMRQSRM: Unknow parameter!\n");
                return APM_L7_ANALYZE_FAIL;
        }

        /* 判断取值正误 */
        if (i_ret != APM_L7_ANALYZE_SUCC)
        {
            frdbg("ENDDTARM: need more data or parse failed!\n");
            return i_ret;
        }
        /* 为取下一个参数做初始化准备 */
        p_st_fragment->i_param_cp = DRDA_CP_NULL;
    }

    /* 根据协议可知svrcod是8时,sqlstate Not returned or 2D528 or 2D529, 取2D528 */
    if (p_st_resp->i64_svrcod == 8 && p_st_resp->i_error_code == 0)
    {
        snprintf(p_st_resp->arr_sqlstate, sizeof(p_st_resp->arr_sqlstate), "2D528");
        /* 2D528对应的error code是: -426/-30090, 取-426 */
        p_st_resp->i_error_code = -426;
        //snprintf(p_st_resp->arr_sqlstate, sizeof(p_st_resp->arr_sqlstate), "2D529");
        /* 58009对应的error code是: -427, -30090 */
        //p_st_resp->i_error_code = -427;
    }
    p_st_fragment->i_req_resp_cp = DRDA_CP_NULL;
    return APM_L7_ANALYZE_SUCC;
}